home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / et / et3_0-a1.lha / et3 / src / ObjectTable.C < prev    next >
C/C++ Source or Header  |  1992-06-16  |  7KB  |  353 lines

  1. #ifdef __GNUG__
  2. #pragma implementation
  3. #endif
  4.  
  5. #include "ObjectTable.h"
  6.  
  7. #include "Class.h"
  8. #include "OrdColl.h"
  9. #include "Set.h"
  10. #include "System.h"
  11. #include "Error.h"
  12. #include "ClassManager.h"
  13. #include "String.h"
  14. #include "CmdNo.h"
  15. #include "Math.h"
  16.  
  17. ObjectTable *gObjectTable;
  18. extern void ETCleanup();
  19.  
  20. static bool rlock;
  21. static int lasts;
  22.  
  23. //---- ObjectTable -------------------------------------------------------------
  24.     
  25. NewMetaImpl(ObjectTable,Object, (TVP(table,size), T(tally), TP(delayed)));
  26.  
  27. bool ObjectTable::died;
  28. Object **ObjectTable::table;
  29. int ObjectTable::size, ObjectTable::tally;
  30. OrdCollection *ObjectTable::delayed, *ObjectTable::rdelayed;
  31. int ObjectTable::iterlevel;
  32. Class *ObjectTable::tab[300];
  33.  
  34. ObjectTable::ObjectTable()
  35. {
  36.     if (gObjectTable)
  37.     Error("ObjectTable", "only one instance of ObjectTable");
  38.     size= Math::NextPrime(10000);
  39.     table= new Object* [size];
  40. }
  41.  
  42. ObjectTable::~ObjectTable()
  43. {
  44.     SafeDelete(delayed);
  45.     SafeDelete(rdelayed);
  46. }
  47.  
  48. //---- static members --------------------------------------------------------
  49.  
  50. void ObjectTable::Add(Object *op)
  51. {
  52.     static bool olock= FALSE;
  53.     
  54.     if (op == 0) {
  55.     ::Error("ObjectTable::Add", "op is 0");
  56.     return;
  57.     }
  58.     if (died || olock || op->TestFlag(cObjIsProto))
  59.     return;
  60.     if (gObjectTable == 0) {
  61.     olock= TRUE;
  62.     gObjectTable= new ObjectTable;
  63.     olock= FALSE;
  64.     Add(gObjectTable);
  65.     }
  66.     if (iterlevel > 0) {
  67.     if (delayed == 0) {
  68.         olock= TRUE;
  69.         delayed= new OrdCollection;
  70.         olock= FALSE;
  71.     }
  72.     delayed->Add(op);
  73.     } else {
  74.     table[FindElement(op)]= op;
  75.     tally++;
  76.     if (HighWaterMark())
  77.         Expand(2 * size);
  78.     }
  79. }
  80.  
  81. void ObjectTable::Remove(Object *op)
  82. {
  83.     if (op == 0)
  84.     ::Error("ObjectTable::Remove", "remove 0 from ObjectTable");
  85.     if (/* died || */ op->TestFlag(cObjIsProto) || rlock)
  86.     return;
  87.  
  88.     Stream::InvalidatePtr(op);
  89.  
  90.     if (delayed && delayed->FindPtr(op)) {
  91.     delayed->RemovePtr(op);
  92.     return;
  93.     }
  94.     if (iterlevel > 0) {
  95.     if (rdelayed == 0) {
  96.         fprintf(stderr, "aha\n");
  97.         rdelayed= new OrdCollection;
  98.     }
  99.     rdelayed->Add(op);
  100.     return;
  101.     }
  102.     if (table == 0)
  103.     return;
  104.     int i= FindElement(op);
  105.     if (table[i] == 0 && !op->TestFlag(cObjIsProto)) { 
  106.     ::Warning("ObjectTable::Remove", "0x%08x not found at %d", (int)op, i);
  107.     for (int j= 0; j < size; j++) {
  108.         if (table[j] == op) {
  109.         ::Error("ObjectTable::Remove", "%d found at %d !!!", (int)op, j);
  110.         i= j;
  111.         }
  112.     }
  113.     }
  114.     table[i]= 0;
  115.     FixCollisions(i);
  116.     tally--;
  117.     
  118.     if (gClassManager) {
  119.     OrdCollection *col= gClassManager->GetClassTable();
  120.     int s= col->Size();
  121.     
  122.     if (tab[0] == 0) {
  123.         if (s < lasts) {
  124.         Iter next(col);
  125.         register Class *cl;
  126.     
  127.         for (int i= 0; cl= (Class*) next(); i++)
  128.             tab[i]= cl;
  129.         }
  130.         lasts= s;
  131.     }
  132.     if (s <= 0) {
  133.         Object *t= gClassManager;
  134.         gClassManager= 0;
  135.         delete t;
  136.     
  137.         ETCleanup();
  138.         SafeDelete(gObjectTable);
  139.         InstanceStatistics();
  140.         died= TRUE;
  141.         SafeDelete(table);
  142.         Storage::FreeAll();
  143.     }
  144.     }
  145. }
  146.  
  147. int ObjectTable::FindElement(Object *op)                                         
  148. {
  149.     register slot, n;
  150.     register Object *slotOp;
  151.  
  152.     if (table == 0)
  153.     return 0;
  154.     slot= ((u_int) op >> 2) % size;
  155.     for (n= 0; n < size; n++) {
  156.     if ((slotOp= table[slot]) == 0) 
  157.         break;
  158.     if (op == slotOp) 
  159.         break;
  160.     if (++slot == size) 
  161.         slot= 0;
  162.     }
  163.     return slot;
  164. }
  165.  
  166. void ObjectTable::FixCollisions (int index)                                         
  167. {
  168.     register int oldIndex, nextIndex;
  169.     register Object *nextObject;
  170.     
  171.     for (oldIndex= index+1; ;oldIndex++) {
  172.     if (oldIndex >= size)
  173.         oldIndex= 0;
  174.     nextObject= table[oldIndex];
  175.     if (nextObject == 0)
  176.         break;
  177.     nextIndex= FindElement(nextObject);
  178.     if (nextIndex != oldIndex) {
  179.         table[nextIndex]= nextObject;
  180.         table[oldIndex]= 0;
  181.     }
  182.     }
  183. }
  184.  
  185. void ObjectTable::Expand(int newSize)
  186. {
  187.     register int i;
  188.     register Object **oldTable= table, *op;
  189.     int oldsize= size;
  190.     newSize= Math::NextPrime(newSize);
  191.     table= new Object*[newSize];
  192.     size= newSize;
  193.     tally= 0;
  194.     for (i= 0; i < oldsize; i++)
  195.     if (op= oldTable[i])
  196.         Add(op);
  197.     delete oldTable; 
  198. }
  199.  
  200. void ObjectTable::HashStatistics()
  201. {
  202. }
  203.  
  204. void ObjectTable::InstanceStatistics()
  205. {
  206.     int i, n, cum= 0;
  207.  
  208.     if (tally == 0)
  209.     return;
  210.     
  211.     for (i= 0; tab[i]; i++)
  212.     tab[i]->ResetInstanceCount();
  213.  
  214.     {
  215.     register Object *op;
  216.     ObjectTableIter next(0);
  217.     while (op= next()) 
  218.         if (op->TestFlag(cObjNonDeleted)) 
  219.         op->IsA()->AddInstance();
  220.         else
  221.         fprintf(stderr, "oops 0x%08x\n", op);
  222.     }
  223.  
  224.     fprintf(stderr, "\n");
  225.     fprintf(stderr, "instances still in ObjectTable\n");
  226.     fprintf(stderr, "class                     cnt    size\n");
  227.     fprintf(stderr, "=====================================\n");
  228.     for (i= 0; tab[i]; i++) {
  229.     n= tab[i]->GetInstanceCount();
  230.     if (n > 0) {
  231.         fprintf(stderr, "%-20s %8d%8d\n", tab[i]->Name(), n, tab[i]->Size());
  232.         cum+= n;
  233.     }
  234.     }
  235.     fprintf(stderr, "-------------------------------------\n");
  236.     fprintf(stderr, "Total                        %8d\n", cum);
  237.     fprintf(stderr, "=====================================\n");
  238.     fprintf(stderr, "\n");
  239. }
  240.  
  241. void ObjectTable::UpdateInstCount(bool heaponly)
  242. {
  243.     register Object *op;
  244.     
  245.     if (table == 0)
  246.     return;
  247.     
  248.     gClassManager->GetClassTable()->ForEach(Class,ResetInstanceCount)();
  249.     
  250.     ObjectTableIter next(0);
  251.     if (heaponly) {
  252.     while (op= next())
  253.         if (op->IsShared())
  254.         op->IsA()->AddInstance();
  255.     } else {
  256.     while (op= next())
  257.         op->IsA()->AddInstance();
  258.     }
  259. }
  260.  
  261. void *ObjectTable::CheckPtrAndWarn(char *msg, void *vp)
  262.     if (table && vp && table[FindElement((Object*)vp)]) {
  263.     Remove((Object*)vp);
  264.     ::Warning("ObjectTable::CheckPtrAndWarn", "%s (0x%08x)\n", msg, vp);
  265.     }
  266.     return vp;
  267. }
  268.  
  269. Object *ObjectTable::SomeInstance(Class *cl)
  270. {
  271.     register Object *op;
  272.     ObjectTableIter next(0);
  273.     while (op= next())
  274.     if (op->IsA()->isKindOf(cl))
  275.         break;
  276.     return op;
  277. }
  278.  
  279. Object *ObjectTable::SomeMember(Class *cl)
  280. {
  281.     register Object *op;
  282.     ObjectTableIter next(0);
  283.     while (op= next())
  284.     if (op->IsA() == cl)
  285.         break;
  286.     return op;
  287. }
  288.  
  289. //---- ObjectTableIter ---------------------------------------------------------
  290.  
  291. ObjectTableIter::ObjectTableIter(Class *cl, bool mem)
  292. {
  293.     ObjectTable::iterlevel++;
  294.     cursor= 0;
  295.     fromClass= cl;
  296.     members= mem;
  297. }
  298.  
  299. ObjectTableIter::~ObjectTableIter()
  300. {
  301.     --ObjectTable::iterlevel;
  302.     if (ObjectTable::iterlevel <= 0) {
  303.     register Object *op;
  304.     if (ObjectTable::delayed) {
  305.         Iter next(ObjectTable::delayed);
  306.         while (op= next())
  307.         ObjectTable::Add(op);
  308.         rlock= TRUE;
  309.         SafeDelete(ObjectTable::delayed);
  310.         rlock= FALSE;
  311.     }
  312.     if (ObjectTable::rdelayed) {
  313.         Iter next(ObjectTable::rdelayed);
  314.         while (op= next())
  315.         ObjectTable::Remove(op);
  316.         rlock= TRUE;
  317.         SafeDelete(ObjectTable::rdelayed);
  318.         rlock= FALSE;
  319.     }
  320.     }
  321. }
  322.  
  323. Object *ObjectTableIter::operator()()
  324. {
  325.     if (ObjectTable::table == 0)
  326.     return 0;
  327.     register Object *op, **t= ObjectTable::table;
  328.     int s= ObjectTable::size;
  329.     
  330.     for ( ; cursor < s ; cursor++) {
  331.     if (op= t[cursor]) {
  332.         if (fromClass == 0)
  333.         break;
  334.         if (members && fromClass == op->IsA())
  335.         break;
  336.         if (!members && op->IsA()->isKindOf(fromClass))
  337.         break;
  338.     }
  339.     }
  340.     return cursor < s ? t[cursor++] : 0;           
  341. }
  342.  
  343. void gIsA(Object *op)
  344. {
  345.     if (op == 0 || !ObjectTable::PtrIsValid(op)) 
  346.     return;
  347.  
  348.     fprintf(stderr, "%s\n", op->ClassName());
  349.     return;
  350. }
  351.  
  352.